package rulePackage;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.uml2.uml.internal.resource.UMLLoadImpl;

import backboneCode.*;

public class RuleSetCollection {

	private static List<Rules> ruleList;
	private static String typeOfRuleSet;
		
	public static RuleSet AddConstraintRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "ConstraintRuleSet";
		ruleList = NewList();
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddTaggedValueRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "TaggedValueRuleSet";
		ruleList = NewList();

		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddRelationshipRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "RelationshipRuleSet";
		ruleList = NewList();
		org.eclipse.uml2.uml.Property prop;
		
		for (org.eclipse.uml2.uml.Element member : umlClass.getOwnedMembers()) {
			//Check to see that it's a property
			if (!(member instanceof org.eclipse.uml2.uml.Property))
				continue;
			
			prop = (org.eclipse.uml2.uml.Property) member;
			if (prop.getAssociation() == null)
				continue;
			//Check to see that the association has the correct stereotype
			for (org.eclipse.uml2.uml.Stereotype stereotype : prop.getAssociation().getAppliedStereotypes()) {
				if (stereotype.getName().compareToIgnoreCase("Dependency") == 0 ||
					stereotype.getName().compareToIgnoreCase("Realization") == 0 ||
					stereotype.getName().compareToIgnoreCase("Generalization") == 0) {
					String stereotypeName = stereotype.getName();
					ruleList.add(new Rules(umlClass.getName(), ((org.eclipse.uml2.uml.Class)prop.getType()).getName(), stereotypeName,
							prop.getLower(), prop.getUpper(), prop.getVisibility().getName()));
				}
			}
		}
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddPackageCompositeRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "PackageCompositeRuleSet";
		ruleList = NewList();
		
		org.eclipse.uml2.uml.Property property;
		
		for (org.eclipse.uml2.uml.NamedElement member : umlClass.getOwnedMembers()) {
			if (!(member instanceof org.eclipse.uml2.uml.Property)) {
				continue;
			}	
			property = (org.eclipse.uml2.uml.Property) member;
			if (property.isComposite() && property.isNavigable()) {
				org.eclipse.uml2.uml.Class otherEndClass = (org.eclipse.uml2.uml.Class)property.getType();
				if (!otherEndClass.getAppliedStereotypes().isEmpty()) {
					for (org.eclipse.uml2.uml.Stereotype stereotype : otherEndClass.getAppliedStereotypes()) {
						ruleList.add(new Rules(otherEndClass.getName(), stereotype.getName(), 
								property.getLower(), property.getUpper(),
								umlClass.getName(), "Package", otherEndClass.getVisibility().getName()));
					}
				} else {
					ruleList.add(new Rules(otherEndClass.getName(), "Class", 
							property.getLower(), property.getUpper(),
							umlClass.getName(), "Package", otherEndClass.getVisibility().getName()));
				}
			}
		}
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddAssociationRuleSet(org.eclipse.uml2.uml.Class umlClass, String umlStereotype_String) {
		typeOfRuleSet = "AssociationRuleSet";
		ruleList = NewList();
			
		for (org.eclipse.uml2.uml.Association member : umlClass.getAssociations()) {
			//Check to see that the association has the correct stereotype, or none.
			boolean cont = false;
			for (org.eclipse.uml2.uml.Stereotype stereotype : member.getAppliedStereotypes()) {
				if (stereotype.getName().compareToIgnoreCase("Association") == 0)
					cont = true;
			}
			if (member.getAppliedStereotypes().isEmpty())
				cont = true;
			if (!cont)
				continue;
			
			boolean PackageComposite = false;
			for (org.eclipse.uml2.uml.Property prop : member.getMemberEnds()) {
				for (org.eclipse.uml2.uml.Stereotype elementStereotype : ((org.eclipse.uml2.uml.Class)prop.getType()).getAppliedStereotypes()) {
					if (elementStereotype.getName().compareToIgnoreCase("Package") == 0 &&
							prop.getOtherEnd().getAggregation().getName().compareToIgnoreCase("Composite") == 0)
						PackageComposite = true;
				}
			}
			if (PackageComposite)
				continue;
			
			for (org.eclipse.uml2.uml.Property prop : member.getMemberEnds()) {
				if (((org.eclipse.uml2.uml.Class)prop.getType()).getName().compareTo(umlClass.getName()) != 0)
					continue;
								
				ruleList.add(new Rules(umlClass.getName(), prop.getOtherEnd().getLower(), prop.getOtherEnd().getUpper(),
						((org.eclipse.uml2.uml.Class)prop.getOtherEnd().getType()).getName(),
						prop.isNavigable(), prop.getAggregation().getName(), prop.getVisibility().getName()));
			}
		}
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddAttributeRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "AttributeRuleSet";
		ruleList = NewList();

		for (org.eclipse.uml2.uml.Property attribute : umlClass.getAllAttributes()) {
			if (attribute.getAssociation() instanceof org.eclipse.uml2.uml.Association)
				continue;
			
			org.eclipse.uml2.uml.Type type = attribute.getType();
			String stringType = "";
			String stringDefault = "";
			if (type == null)
				stringType = "@";
			else
				stringType = type.toString().substring(type.toString().lastIndexOf('#') + 1, type.toString().lastIndexOf(')'));
			
			if (attribute.getDefault() != null)
				stringDefault = attribute.getDefault();
			if (attribute.getName().lastIndexOf('%') == -1)
				ruleList.add(new Rules(attribute.getName(), stringType, stringDefault, attribute.getVisibility().getName(), 1, 1));
			else
				ruleList.add(new Rules(attribute.getName(), stringType, stringDefault, attribute.getVisibility().getName(), 0, -1));
		}		
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	public static RuleSet AddOperationRuleSet(org.eclipse.uml2.uml.Class umlClass) {
		typeOfRuleSet = "OperationRuleSet";
		ruleList = NewList();
		
		ruleList = CheckList(ruleList);		
		return new RuleSet(ruleList, typeOfRuleSet);
	}
	
	private static List<Rules> CheckList(List<Rules> ruleList) {
		
		if (ruleList.isEmpty())
			return null;
		
		return ruleList;
	}
	
	private static ArrayList<Rules> NewList() {
		return new ArrayList<Rules>();
	}
}
